<template>
  <div>
    <el-descriptions size="small" title="mBean 信息" class="margin-top" border :column="1">
      <el-descriptions-item label="ObjectName">{{ nameInfo.ref }}</el-descriptions-item>
      <el-descriptions-item label="ClassName">{{ mBeanInfo.className }}</el-descriptions-item>
      <el-descriptions-item label="description">{{ mBeanInfo.description }}</el-descriptions-item>
    </el-descriptions>

    <el-collapse>
      <!-- 属性信息 -->
      <template v-if="mBeanInfo && mBeanInfo.attributes">
        <el-collapse-item title="属性信息" name="1">
          <el-table
            :data="mBeanInfo.attributes"
            border
            stripe
            highlight-current-row
            size="mini"
            style="width: 100%"
          >
            <el-table-column prop="name" label="属性名" />
            <el-table-column prop="value" label="属性值">
              <template slot-scope="scope">
                {{ formatterValue(scope.row) }}
              </template>
            </el-table-column>
            <el-table-column prop="type" label="类型" width="150">
              <template slot-scope="scope">
                {{ realType(scope.row.type) }}
              </template>
            </el-table-column>
            <el-table-column prop="readable" label="可读" width="80">
              <template slot-scope="scope">{{ scope.row.readable }}</template>
            </el-table-column>
            <el-table-column prop="writable" label="可写" width="80">
              <template slot-scope="scope">{{ scope.row.writable }}</template>
            </el-table-column>
            <el-table-column prop="description" label="描述" />
          </el-table>
        </el-collapse-item>
      </template>

      <!-- 方法信息 -->
      <template v-if="mBeanInfo && mBeanInfo.operations">
        <el-collapse-item title="方法信息">
          <ul class="method-wrapper">
            <li v-for="operation in mBeanInfo.operations" :key="'operation'+operation.name" class="method">
              {{ realType(operation.returnType) }} <el-button :disabled="!operation.allowCall" type="text" size="small" @click="invokeMethod(operation)">{{ operation.name }}</el-button>(
              <template v-if="operation.signature">
                <span v-for="(param,index) in operation.signature" :key="'param'+param.name" class="param">
                  <template v-if="index !== 0"> , </template>
                  {{ realType(param.type) }}
                  <el-input v-model="param.value" size="mini" :placeholder="param.name" style="width: 100px" />
                </span>
              </template>
              )
            </li>
          </ul>
        </el-collapse-item>
      </template>

      <!-- 通知信息 -->
      <template v-if="mBeanInfo && mBeanInfo.notifications">
        <el-collapse-item title="通知信息">
          暂未实现
        </el-collapse-item>
      </template>
    </el-collapse>

    <!-- 方法调用结果 -->
    <el-dialog title="调用结果" :visible.sync="dialog.visible">
      <json-editor :json="dialog.data" />
    </el-dialog>
  </div>
</template>

<script>
import jvm from '@/api/jvm'

import JsonEditor from '@/components/JsonEditor'
export default {
  name: 'Mbeanview',
  components: { JsonEditor },
  props: {
    nameInfo: {
      type: Object
    },
    connName: {
      type: String
    }
  },
  data() {
    return {
      mBeanInfo: {},
      dialog: {
        visible: false,
        data: null
      }
    }
  },
  mounted() {

  },
  methods: {
    invokeMethod(operation) {
      console.log(operation, 'operation')
      let signature = null
      let values = null
      if (operation.signature) {
        signature = operation.signature.map(s => s.type)
        values = operation.signature.map(s => s.value)
      }

      const invokeParam = { connName: this.connName, beanName: this.nameInfo.ref, operation: operation.name, signature: signature, params: values }
      jvm.invoke(invokeParam).then(res => {
        this.dialog.visible = true
        this.dialog.data = res.data
      })
    },
    formatterValue(row) {
      if (row.type.startsWith('[') && row.value) {
        return row.value.join(',')
      }

      return row.value
    },
    realType(type) {
      if (type.startsWith('[L')) {
        const className = type.substring(2)
        const classSimpleName = className.substring(className.lastIndexOf('.') + 1).replaceAll(';', '')
        return classSimpleName + '[]'
      }
      if (type.startsWith('[')) {
        const componentType = type.charAt(1)
        switch (componentType) {
          case 'I':
            return 'int []'
          case 'J':
            return 'long []'
          case 'Z':
            return 'boolean []'
          case 'D':
            return 'double []'
          case 'F':
            return 'float []'
          case 'L':
            return type.substring(2) + ' []'
        }
        return componentType + ' []'
      }
      return type
    },
    init() {
      if (this.nameInfo) {
        jvm.detail(this.connName, this.nameInfo.ref).then(res => {
          const mBeanInfo = res.data

          // 方法如果参数有数组, 不可以在线调用
          const operations = mBeanInfo.operations
          if (operations) {
            for (let i = 0; i < operations.length; i++) {
              const signature = operations[i].signature
              if (!signature) {
                operations[i].allowCall = true
                continue
              }
              operations[i].allowCall = true
              for (let j = 0; j < signature.length; j++) {
                if (signature[j].type.startsWith('[')) {
                  operations[i].allowCall = false
                  break
                }
              }
            }
          }

          // 如果有属性, 则获取属性的值
          const attributes = mBeanInfo.attributes
          if (attributes) {
            const names = attributes.map(attribute => attribute.name)
            const attributeMap = {}
            for (let i = 0; i < attributes.length; i++) {
              attributeMap[attributes[i].name] = attributes[i]
            }
            jvm.attrValue(this.connName, this.nameInfo.ref, names.join(',')).then(res => {
              for (let i = 0; i < res.data.length; i++) {
                attributeMap[res.data[i].name].value = res.data[i].value
              }
              mBeanInfo.attributes = Object.values(attributeMap)
              this.mBeanInfo = mBeanInfo
            })
          } else {
            this.mBeanInfo = mBeanInfo
          }
        })
      }
    }
  }
}
</script>

<style scoped>
.method-wrapper{
  list-style-type: none;
  padding: 0;
  margin: 0;

  line-height: 3;
}
.method-wrapper>li{
  padding: 0;
  margin: 0;
}

</style>
